<?php
// +--------------------------------------------------------------------------------------------------------------------
// | 本文件是《FastChat》的一部分，所有代码、文字、图片、样式、风格等版权归作者所有，如有复制、仿冒、抄袭、盗用，FastAdmin和作者将追究法律责任
// +--------------------------------------------------------------------------------------------------------------------
// | @作者: 妙码生花 <1094963513@qq.com>
// +--------------------------------------------------------------------------------------------------------------------
// | @唯一授权链接: https://www.fastadmin.net/store/fastchat.html
// +--------------------------------------------------------------------------------------------------------------------

use think\Db;
use GatewayWorker\Lib\Gateway;
use addons\fastchat\library\Common;

/**
 *
 */
class Message
{
    /**
     * 清退一个链接
     */
    public function clear($client_id)
    {
        Gateway::closeClient($client_id);
    }

    public function ping()
    {
        // 用户端心跳
    }

    /**
     * 直接标记消息已读
     */
    public function read_message($client_id, $data)
    {
        Db::name('fastchat_record')->where('id', $data['record_id'])->update(['status' => 1]);
    }

    /**
     * 推送消息
     */
    public function push_message($client_id, $data)
    {
        if (!isset($data['token']) || !isset($data['service_user'])) {
            Gateway::closeClient($client_id);
        }

        // 验证 token
        $token = Common::getEncryptedToken($data['token']);

        $service_user = Db::name('fastchat_service_user')
            ->where('id', $data['service_user'])
            ->where('status', '1')
            ->where('deletetime', null)
            ->find();

        if (!$service_user || $service_user['token'] != $token) {
            Gateway::closeClient($client_id);
        }

        $service_user_id = $service_user['id'] . '||service_user';

        // 发送消息给用户
        if (isset($data['user']) && $data['user']) {
            $user = explode(',', $data['user']);

            foreach ($user as $value) {
                $session_user = $value . '||user';

                Common::send_message($service_user_id, $session_user, $data);
            }
        }

        // 发送消息给管理员
        if (isset($data['admin']) && $data['admin']) {
            $user = explode(',', $data['admin']);

            foreach ($user as $value) {
                $session_user = $value . '||admin';

                Common::send_message($service_user_id, $session_user, $data);
            }
        }

        // 发送消息给用户组
        if (isset($data['user_group']) && $data['user_group']) {

            // 查得这个组中的所有用户
            $user = Db::name('user')->field('id')->whereIn('group_id', $data['user_group'])->select();

            foreach ($user as $value) {
                $session_user = $value['id'] . '||user';

                Common::send_message($service_user_id, $session_user, $data);
            }
        }

        // 发送消息给管理员组
        if (isset($data['admin_group']) && $data['admin_group']) {

            // 查得这个组中的所有管理员
            $user = Db::name('auth_group_access')->field('uid')->distinct(true)->where('group_id', $data['admin_group'])->select();

            foreach ($user as $value) {
                $session_user = $value['uid'] . '||admin';

                Common::send_message($service_user_id, $session_user, $data);
            }
        }

    }

    public function del_session($client_id, $data)
    {

        $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();

        if (!$session_info) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'del_session', 'code' => 0, 'msg' => '会话找不到啦！']));
        }

        if ($session_info['deleteuser'] && $session_info['deleteuser'] != $_SESSION['user_id']) {
            Db::name('fastchat_session')->where('id', $data['session_id'])->update(['deletetime' => time()]);
        } else {
            Db::name('fastchat_session')->where('id', $data['session_id'])->update(['deleteuser' => $_SESSION['user_id']]);
        }

    }

    public function send_message($client_id, $data)
    {

        if (!isset($data['session_id'])) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,会话找不到啦！']));
        }

        $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();

        if (!$session_info) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'send_message', 'code' => 0, 'msg' => '发送失败,会话找不到啦！']));
        }

        // 确定收信人
        $session_user = Common::session_user($session_info);

        $res = Common::send_message($_SESSION['user_id'], $session_user, $data['message']);

        Gateway::sendToClient($client_id, json_encode($res));
    }

    /**
     * 聊天记录
     * @return void
     */
    public function chat_record($client_id, $data)
    {

        $page_count = 20;//一次加载20条

        if (!isset($data['session_id'])) {
            Gateway::sendToClient($client_id, json_encode([
                'msgtype' => 'chat_record', 'code' => 1, 'data' =>
                    [
                        'chat_record'  => [],
                        'session_info' => [
                            'nickname' => '无会话'
                        ],
                        'next_page'    => 'done',
                        'page'         => $data['page']
                    ]
            ]));
            return;
        }

        if (!isset($data['page'])) {
            $data['page'] = 1;
        }

        $chat_record_count = Db::name('fastchat_record')
            ->where('session_id', $data['session_id'])
            ->count('id');

        $page_number = ceil($chat_record_count / $page_count);

        if ($data['page'] == 1) {
            $min = 0;
        } else {
            $min = ((int)$data['page'] - 1) * $page_count;
            if (isset($data['unexpected_records']) && $data['unexpected_records'] > 0) {
                $min += $data['unexpected_records'];
            }
        }

        // 会话信息
        $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();

        if (!$session_info) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'chat_record', 'code' => 0, 'msg' => '会话找不到啦！']));
        }

        // 标记此会话所有不是当前用户发的消息为已读->SQL不使用不等于->查得会话对象的ID
        $session_user = Common::session_user($session_info);
        Db::name('fastchat_record')->where('sender', $session_user)->where('status', 0)->update(['status' => 1]);

        $session_user_info = Common::user_info($session_user);

        // 是否屏蔽此人
        $session_user_info['blacklist'] = Db::name('fastchat_blacklist')
            ->where('user_id', $_SESSION['user_id'])
            ->where('session_user_id', $session_user)
            ->value('id');

        $chat_record = Db::name('fastchat_record')
            ->where('session_id', $data['session_id'])
            ->limit($min, $page_count)
            ->order('createtime desc')
            ->select();

        // 消息按时间分组
        if ($chat_record) {

            $record_temp = [];
            $createtime  = $chat_record[0]['createtime'];

            foreach ($chat_record as $value) {

                $value['sender']  = ($value['sender'] == $_SESSION['user_id']) ? 'me' : 'you';
                $value['message'] = htmlspecialchars_decode($value['message']);

                if ($value['createtime'] - $createtime >= 3600) {
                    $createtime = $value['createtime'];
                }
                $record_temp[$createtime][] = $value;
            }

            unset($chat_record);

            foreach ($record_temp as $key => $value) {
                $chat_record[] = [
                    'datetime' => Common::format_time($key),
                    'data'     => $value
                ];
            }
            unset($record_temp);
        } else {
            $chat_record[] = [
                'datetime' => '还没有消息',
                'data'     => []
            ];
        }

        Gateway::sendToClient($client_id, json_encode([
            'msgtype' => 'chat_record', 'code' => 1, 'data' =>
                [
                    'chat_record'  => $chat_record ?? [],
                    'session_info' => $session_user_info,
                    'next_page'    => ($data['page'] >= $page_number) ? 'done' : $data['page'] + 1,
                    'page'         => $data['page']
                ]
        ]));
    }

    /**
     * 获取会话列表
     */
    public function session_list($client_id, $data)
    {
        $user = Common::user_info($_SESSION['user_id']);

        $session_list = Db::name('fastchat_session')
            ->where(function ($query) {
                $query->where('user_id', $_SESSION['user_id'])->where('deletetime', null);
            })->whereOr(function ($query) use ($user) {
                $query->where('session_user_id', $user['id'])->where('session_type', $user['session_type'])->where('deletetime', null);
            })
            ->order('createtime desc')
            ->select();

        if (!$session_list) {
            // 添加需要自动添加的会话
            $auto_add_session = Db::name('fastchat_service_user')
                ->field('CONCAT(id,"||service_user") as id,CONCAT(admin_id,"||admin") as admin_id,welcome_news,add_sessiondata')
                ->where("add_sessiondata='0' OR add_sessiondata='1'")
                ->where('status', '1')
                ->where('deletetime', null)
                ->select();

            foreach ($auto_add_session as $value) {

                if (($value['add_sessiondata'] == 0 && Gateway::isUidOnline($value['id'])) || $value['add_sessiondata'] == 1) {

                    $session = $session_list[] = Common::add_session($value['id']);
                    // 发送欢迎消息
                    if ($value['welcome_news']) {

                        $message = [
                            'session_id' => $session['id'],
                            'sender'     => $value['id'],
                            'message'    => $value['welcome_news'],
                            'createtime' => time()
                        ];

                        Db::name('fastchat_record')->insert($message);
                    }

                }
            }
        }

        $session_list = array_reverse($session_list);

        foreach ($session_list as $key => $value) {

            if ($value['deleteuser'] == $_SESSION['user_id']) {
                unset($session_list[$key]);
                continue;
            }

            $session_list[$key]['last_time'] = Common::format_time($value['createtime']);

            // 最后一条聊天记录
            $last_message = Db::name('fastchat_record')
                ->where('session_id', $value['id'])
                ->order('createtime desc')
                ->find();

            $session_list[$key]['session_user'] = $session_user = Common::session_user($value);
            $session_user_info                  = Common::user_info($session_user);

            $session_list[$key]['avatar']   = $session_user_info['avatar'];
            $session_list[$key]['nickname'] = $session_user_info['nickname'];

            if ($last_message) {

                $session_list[$key]['last_message'] = Common::session_message($last_message['message']);
                $last_message['message']            = htmlspecialchars_decode($last_message['message']);
                $session_list[$key]['last_time']    = Common::format_time($last_message['createtime']);
            } elseif (isset($session_user_info['bio'])) {
                $session_list[$key]['last_message'] = $session_user_info['bio'];
            } else {
                $session_list[$key]['last_message'] = '';
            }

            // 未读消息条数->查询不是当前用户发送的消息

            $session_list[$key]['unread_msg_count'] = Db::name('fastchat_record')
                ->where('session_id', $value['id'])
                ->where('sender', $session_user)
                ->where('status', 0)
                ->count('id');

            // 会话对象是否在线
            if ($session_user_info['session_type'] == 5 && $session_user_info['online_status'] == 0) {
                $session_list[$key]['online'] = 1;
            } else {
                $session_list[$key]['online'] = Gateway::isUidOnline($session_user);
            }
        }

        $session_list = array_values($session_list);

        Gateway::sendToClient($client_id, json_encode(['msgtype' => 'message_list', 'data' => $session_list]));
    }

    /**
     * 搜索用户
     */
    public function search_user($client_id, $keywords)
    {
        $config_data = get_addon_config('fastchat');

        $where = array();

        $session_type = explode(',', $config_data['session_type']);
        foreach ($session_type as $value) {
            switch ($value) {
                case "username":
                    $where['username'] = ['like', '%' . $keywords . '%'];
                    break;
                case "usermobile":
                    $where['mobile'] = $keywords;
                    break;
                case "userid":
                    $where['id'] = $keywords;
                    break;
                case "nickname":
                    $where['nickname'] = ['like', '%' . $keywords . '%'];
                    break;
            }
        }

        // 每种身份最多搜索出 8 位预选人,可随意调整
        $user_list = Db::name('user')->field('CONCAT(id,"||user") as id,nickname,avatar')->whereOr($where)->limit(8)->select();

        unset($where['mobile']);
        if ($config_data['user_to_admin'] == 1) {
            $admin_list = Db::name('admin')->field('CONCAT(id,"||admin") as id,nickname,avatar')->whereOr($where)->limit(8)->select();
        } else {
            $admin_list = array();
        }


        if (isset($where['username'])) {
            $where['nickname'] = $where['username'];
            unset($where['username']);
        }

        $service_users = Db::name('fastchat_service_user')
            ->field('CONCAT(id,"||service_user") as id,nickname,avatar')
            ->whereOr($where)
            ->limit(8)
            ->select();

        $user_list = array_merge($user_list, $admin_list, $service_users);

        foreach ($user_list as $key => $value) {
            $user_list[$key]['avatar'] = $value['avatar'] ? cdnurl($value['avatar'], $_SESSION['origin']) : $_SESSION['origin'] . '/assets/img/avatar.png';

            // 去掉用户自己
            if ($value['id'] == $_SESSION['user_id']) {
                unset($user_list[$key]);
            }
        }

        $user_list = array_values($user_list);

        Gateway::sendToClient($client_id, json_encode(['msgtype' => 'search_user', 'data' => $user_list]));
    }

    /**
     * 屏蔽会话
     */
    public function shielding_session($client_id, $data)
    {
        if (!isset($data['session_id']) || $data['session_id'] <= 0) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '会话找不到啦！']));
            return;
        }

        $session_info = Db::name('fastchat_session')->where('id', $data['session_id'])->find();

        if (!$session_info) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '会话找不到啦！']));
        }

        // 获取会话人
        $session_user_id = Common::session_user($session_info);

        $blacklist_id = Db::name('fastchat_blacklist')
            ->where('user_id', $_SESSION['user_id'])
            ->where('session_user_id', $session_user_id)
            ->value('id');

        if ($blacklist_id) {
            if (Db::name('fastchat_blacklist')->where('id', $blacklist_id)->delete()) {
                Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 2, 'session_id' => $data['session_id']]));
            } else {
                Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '操作失败,请重试！']));
            }

            return;
        }

        $blacklist = [
            'user_id'         => $_SESSION['user_id'],
            'session_user_id' => $session_user_id,
            'createtime'      => time()
        ];

        if (Db::name('fastchat_blacklist')->insert($blacklist)) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 1, 'session_id' => $data['session_id']]));
        } else {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'shielding_session', 'code' => 0, 'msg' => '操作失败,请重试！']));
        }
    }

    /**
     * 添加会话
     */
    public function add_session($client_id, $data)
    {
        $config_data = get_addon_config('fastchat');

        if (!isset($data['user_id']) || $data['user_id'] <= 0) {
            Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '用户找不到啦！']));
            return;
        }

        $session_user = Common::user_info($data['user_id']);
        $user_info    = Common::user_info($_SESSION['user_id']);

        if ($user_info['session_type'] == 2 || $user_info['session_type'] == 3 || $user_info['session_type'] == 4) {

            if (!$config_data['anonymous_to_admin'] && $session_user['session_type'] == 1) {
                Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '禁止匿名向管理员发起会话！']));
                return;
            }

            if (!$config_data['anonymous_to_user'] && $session_user['session_type'] == 0) {
                Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 0, 'msg' => '禁止匿名向用户发起会话！']));
                return;
            }
        }

        // 插入会话表
        $existing_session = false;

        $session = Db::name('fastchat_session')->where(function ($query) use ($session_user) {

            $query->where('user_id', $_SESSION['user_id'])
                ->where('session_type', $session_user['session_type'])
                ->where('session_user_id', $session_user['id']);

        })
            ->whereOr(function ($query) use ($data, $user_info) {

                $query->where('user_id', $data['user_id'])
                    ->where('session_type', $user_info['session_type'])
                    ->where('session_user_id', $user_info['id']);

            })
            ->find();

        if (!$session) {

            $session = [
                'user_id'         => $_SESSION['user_id'],
                'session_type'    => $session_user['session_type'],
                'session_user_id' => $session_user['id'],
                'createtime'      => time()
            ];

            Db::name('fastchat_session')->insert($session);
            $session['id'] = Db::name('fastchat_session')->getLastInsID();
        } else {
            // 会话列表已存在此会话，修改会话的时间
            $existing_session = true;

            if ($session['deletetime']) {
                // deleteuser 改为对方
                $session_user_id = Common::session_user($session);
                Db::name('fastchat_session')->where('id', $session['id'])->update(['deleteuser' => $session_user_id, 'deletetime' => null, 'createtime' => time()]);
            } elseif ($session['deleteuser'] == $_SESSION['user_id']) {
                Db::name('fastchat_session')->where('id', $session['id'])->update(['deleteuser' => '', 'deletetime' => null, 'createtime' => time()]);
            } else {
                Db::name('fastchat_session')->where('id', $session['id'])->update(['createtime' => time()]);
            }
        }

        // 读取最后一条聊天记录
        $last_message = Db::name('fastchat_record')
            ->where('session_id', $session['id'])
            ->order('createtime desc')
            ->find();

        if ($last_message) {
            $last_message_text = $last_message['message'];
        } elseif (isset($session_user['bio'])) {
            $last_message_text = $session_user['bio'];
        } else {
            $last_message_text = '';
        }

        $blacklist_id = Db::name('fastchat_blacklist')
            ->where('user_id', $_SESSION['user_id'])
            ->where('session_user_id', $data['user_id'])
            ->value('id');

        $resdata = [
            'id'               => $session['id'],
            'avatar'           => $session_user['avatar'],
            'nickname'         => $session_user['nickname'],
            'last_message'     => Common::session_message($last_message_text),
            'existing_session' => $existing_session,
            'blacklist'        => $blacklist_id
        ];

        // 会话对象是否在线
        if ($session_user['session_type'] == 5 && $session_user['online_status'] == 0) {
            $resdata['online'] = 1;
        } else {

            if (!isset($session_user_id)) {
                $session_user_id = Common::session_user($session);
            }

            $resdata['session_user'] = $session_user_id;
            $resdata['online']       = Gateway::isUidOnline($session_user_id);
        }

        if ($existing_session || !isset($last_message['createtime'])) {
            $resdata['last_time'] = Common::format_time();
        } else {
            $resdata['last_time'] = Common::format_time($last_message['createtime']);
        }

        Gateway::sendToClient($client_id, json_encode(['msgtype' => 'add_session', 'code' => 1, 'data' => $resdata]));
    }
}